//
//  CourseBookingsViewController.m
//  mUBB
//
//  Created by Cosmin Stirbu on 3/3/13.
//  Copyright (c) 2013 Cosmin Stirbu. All rights reserved.
//

#import "CourseBookingsViewController.h"
#import "BookingsManager.h"
#import "BookingCell.h"
#import "CenteredTextCell.h"
#import "StartupManager.h"
#import <EventKit/EventKit.h>
#import <EventKitUI/EventKitUI.h>
#import "WSError.h"
#import "Constants.h"

#define BOOKING_DATE_FORMAT @"yyyy-MM-dd HH:mm"

#define TEACHER_ACTION_SHEET 1
#define REGULAR_USER_ACTION_SHEET 2
#define FUTURE_BOOKINGS_ACTION_SHEET 3

@interface CourseBookingsViewController ()

@end

@implementation CourseBookingsViewController

@synthesize categorySegmentedControl, bookingsTableView, categoryToolbar;

- (id)initWithNibName:(NSString *)nibNameOrNil course:(Course *)course
{
    self = [super initWithNibName:nibNameOrNil bundle:nil];
    if (self) {
        // Custom initialization
        _course = course;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    for (Teacher *teacher in _course.teachers) {
        if (teacher.teacherId == [[[ConfigurationManager instance] applicationConfigValueForKey:USER_ID] integerValue]) {
            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addBooking)];
            break;
        }
    }
    categoryToolbar.tintColor = self.navigationController.navigationBar.tintColor;
    // Get The bookings
    [self getBookings];
}

- (void)setUpTheUI {
    [categorySegmentedControl removeAllSegments];
    NSInteger index = 0;
    for (TypeOfClass *typeOfClass in _sortedTypesOfClasses) {
        [categorySegmentedControl insertSegmentWithTitle:typeOfClass.name atIndex:index++ animated:YES];
    }
    [categorySegmentedControl setSelectedSegmentIndex:0];
    [self typeOfClassChanged:categorySegmentedControl];
}

#pragma mark - UI Interaction
- (IBAction)typeOfClassChanged:(id)sender {
    TypeOfClass *selectedTypeOfClass = [_sortedTypesOfClasses objectAtIndex:[categorySegmentedControl selectedSegmentIndex]];
    _displayedBookings = [_groupedBookings objectForKey:selectedTypeOfClass];
    [bookingsTableView reloadData];
    [bookingsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    
}

#pragma mark - TableViewDataSource Method

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Check if there are any bookings
    if ([_displayedBookings count] > 0) {
        // If bookings are still available (in the future)
        if ([[BookingsManager instance] bookingsStillAvailable:_displayedBookings]) {
            return [_displayedBookings count] + 1;
        } else {
            // All bookings are in the past
            return [_displayedBookings count];
        }
    } else {
        return 0;
    }
}

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row < [_displayedBookings count]) {
        // Booking cell
        return BOOKING_CELL_HEIGHT;
    } else if (indexPath.row == [_displayedBookings count]) {
        return CENTERED_CELL_HEIGHT;
    }
    return 0;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    TypeOfClass *currentTypeOfClass = [_sortedTypesOfClasses objectAtIndex:categorySegmentedControl.selectedSegmentIndex];
    return currentTypeOfClass.name;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell;
    if (indexPath.row < [_displayedBookings count]) {
        // Booking cell
        cell = [tableView dequeueReusableCellWithIdentifier:@"BookingCell"];
        if (cell == nil) {
            NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"BookingCell" owner:self options:nil];
            cell = [array objectAtIndex:0];
        }
        Booking *booking = [_displayedBookings objectAtIndex:indexPath.row];
        BookingCell *bookingCell = (BookingCell *)cell;
        bookingCell.booking = booking;
        if ([booking.startDate compare:[NSDate date]] == NSOrderedAscending) {
            [bookingCell setSelectionStyle:UITableViewCellSelectionStyleNone];
        } else {
            [bookingCell setSelectionStyle:UITableViewCellSelectionStyleBlue];
        }
        
    } else {
        // Add bookings to calendar cell
        cell = [tableView dequeueReusableCellWithIdentifier:@"CenteredCell"];
        if (cell == nil) {
            NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"CenteredTextCell" owner:self options:nil];
            cell = [array objectAtIndex:0];
        }
        CenteredTextCell *addCell = (CenteredTextCell *)cell;
        addCell.centeredLabel.text = NSLocalizedString(@"ADD_TO_CALENDAR_CELL", nil);
    }
    return cell;
}

#pragma mark - UITableViewDelegate Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row < [_displayedBookings count]) {
        // Booking cell
        Booking *booking = [_displayedBookings objectAtIndex:indexPath.row];
        NSDate *todayDate = [NSDate date];
        if ([booking.startDate compare:todayDate] == NSOrderedDescending) {
            // Save selected index
            selectedIndex = indexPath;
            
            // Booking is still available
            NSString *firstButtonName = NSLocalizedString(@"BOOKING_SHEET_ADD_TO_CAL", nil);
            if ([[BookingsManager instance] bookingIsInCalendar:booking]) {
                // Booking is already in calendar
                firstButtonName = NSLocalizedString(@"BOOKING_SHEET_DELETE_FROM_CAL", nil);
            }
            if (booking.teacher.teacherId == [[[ConfigurationManager instance] applicationConfigValueForKey:USER_ID] integerValue]) {
                // The user can also edit this booking
                UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:NSLocalizedString(@"ALERT_CANCEL", nil) destructiveButtonTitle:nil otherButtonTitles:firstButtonName, NSLocalizedString(@"BOOKING_SHEET_CHANGE", nil), nil];
                actionSheet.tag = TEACHER_ACTION_SHEET;
                [actionSheet showInView:self.view];
            } else {
                UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:NSLocalizedString(@"ALERT_CANCEL", nil) destructiveButtonTitle:nil otherButtonTitles:firstButtonName, nil];
                actionSheet.tag = REGULAR_USER_ACTION_SHEET;
                [actionSheet showInView:self.view];
            }
        } else {
            [tableView deselectRowAtIndexPath:indexPath animated:NO];
        }
        
    } else {
        // Add all bookings to the calendar
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"BOOKING_SHEET_ADD_ALL_TITLE", nil)  delegate:self cancelButtonTitle:NSLocalizedString(@"ALERT_CANCEL", nil) destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(@"BOOKING_SHEET_ADD_ALL_TO_CAL", nil), nil];
        actionSheet.tag = FUTURE_BOOKINGS_ACTION_SHEET;
        [actionSheet showInView:self.view];
         [tableView deselectRowAtIndexPath:indexPath animated:NO];
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row < [_displayedBookings count]) {
        // Booking cell
        BookingCell *bookingCell = (BookingCell *)cell;
        if ([bookingCell.booking.startDate compare:[NSDate date]] == NSOrderedAscending) {
            // Change the background coulour of the cell
            bookingCell.backgroundColor = [Utils colorWithHexString:[[ConfigurationManager instance] UIConfigValueForKey:@"booking_cell_past_background"]];
        }
    
    }
}


#pragma mark - Private Method
- (void)getBookings {
    [Utils showLoadingOn:self];
    [[BookingsManager instance] getBookingsForCourse:_course delegate:self];
}

- (void)addBooking {
    // Update booking
    UpdateBookingViewController *updateBooking = [[UpdateBookingViewController alloc] initWithNibName:@"UpdateBookingViewController" booking:nil course:_course];
    updateBooking.delegate = self;
    updateBooking.updatingBooking = NO;
    updateBooking.title = _course.courseName;
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:updateBooking];
    [self.navigationController presentModalViewController:navigationController animated:YES];
}

- (void)handleCalendarBookingOperation:(Booking *)booking {
    if ([[BookingsManager instance] bookingIsInCalendar:booking]) {
        // Delete booking
        [[BookingsManager instance] deleteBookingFromCalendar:booking];
    } else {
        EKEventStore *es = [[EKEventStore alloc] init];
        if ([es respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
            // IOS 6
            [es requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
                /* This code will run when uses has made his/her choice */
                if (granted) {
                    // Add Booking
                    [self performSelectorOnMainThread:@selector(addBookingInCalendarWithEKEventViewController:) withObject:booking waitUntilDone:NO];
                }
            }];
        } else {
            // Add Booking
            [self addBookingInCalendarWithEKEventViewController:booking];
        }
    }
}

- (void)addBookingInCalendarWithEKEventViewController:(Booking *)booking {
    EKEventEditViewController *eventViewController = [EKEventEditViewController new];
    EKEventStore *eventStore = [[EKEventStore alloc] init];
    EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
    // Title
    event.title = [NSString stringWithFormat:@"%@ (%@)", booking.course.courseName, booking.typeOfClass.name];
    
    // Start Date
    event.startDate = booking.startDate;
    event.endDate = booking.endDate;
    
    // Teacher + Study groups
    event.notes = [NSString stringWithFormat:@"%@ %@\n%@", booking.teacher.firstName, booking.teacher.lastName, [[BookingsManager instance] stringWithBookingStudyGroups:booking.studyGroups]];
    
    // Location
    event.location = [NSString stringWithFormat:@"%@, %@", booking.room.name, booking.room.building.name];
    
    [event setCalendar:[eventStore defaultCalendarForNewEvents]];
    
    eventViewController.event = event;
    eventViewController.eventStore = eventStore;
    
    eventViewController.editViewDelegate = self;
    [self.navigationController presentModalViewController:eventViewController animated:YES];
}

#pragma  mark - Action Sheet Delegate Methods

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    
    if (actionSheet.tag == REGULAR_USER_ACTION_SHEET) {
        // Regular user action sheet
        if (buttonIndex != actionSheet.cancelButtonIndex) {
            [self handleCalendarBookingOperation:[_displayedBookings objectAtIndex:selectedIndex.row]];
        }
    } else if (actionSheet.tag == TEACHER_ACTION_SHEET) {
        // Teacher action sheet
        if (buttonIndex == 0) {
            // Handle booking in calendar
            [self handleCalendarBookingOperation:[_displayedBookings objectAtIndex:selectedIndex.row]];
        } else if (buttonIndex != actionSheet.cancelButtonIndex) {
            // Update booking
            UpdateBookingViewController *updateBooking = [[UpdateBookingViewController alloc] initWithNibName:@"UpdateBookingViewController" booking:[_displayedBookings objectAtIndex:selectedIndex.row] course:_course];
            updateBooking.delegate = self;
            updateBooking.title = _course.courseName;
            updateBooking.updatingBooking = YES;
            UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:updateBooking];
            [self.navigationController presentModalViewController:navigationController animated:YES];
        }
    } else if (actionSheet.tag == FUTURE_BOOKINGS_ACTION_SHEET) {
        if (buttonIndex != actionSheet.cancelButtonIndex) {
            // Add all bookings to calendar
            NSInteger nrOfAddedBookings = [[BookingsManager instance] addAllFutureEventsToCalendar:_displayedBookings];
            NSString *message = nil;
            if (nrOfAddedBookings > 0) {
                message = [NSString stringWithFormat:NSLocalizedString(@"BOOKINGS_ADDED_IN_CAL", nil), nrOfAddedBookings];
            } else {
                message = NSLocalizedString(@"BOOKINGS_COULDNT_BE_ADDED", nil);
            }
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"ALERT_OK", nil) otherButtonTitles: nil];
            [alertView show];
            
            // The bookings are added to the calendar in a background thread on iOS 6. Dirty workaround
            [bookingsTableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
        }
    }
    [bookingsTableView deselectRowAtIndexPath:selectedIndex animated:NO];
    [bookingsTableView reloadData];
}

#pragma mark - EKEventEditDelegate

- (void)eventEditViewController:(EKEventEditViewController *)controller didCompleteWithAction:(EKEventEditViewAction)action {
    if (action == EKEventEditViewActionSaved) {
        [[BookingsManager instance] saveIdentifier:controller.event forBooking:[_displayedBookings objectAtIndex:selectedIndex.row]];
    }
    [controller dismissModalViewControllerAnimated:YES];
    selectedIndex = nil;
    [bookingsTableView reloadData];
}

#pragma mark - UpdateBookingDelegate Methods 

- (void)didFinishUpdatingBooking:(UpdateBookingViewController *)updateBookingViewController refreshBookings:(BOOL)refreshBookings {
    [updateBookingViewController.navigationController dismissModalViewControllerAnimated:YES];
    if (refreshBookings) {
        [self getBookings];
    }
}

#pragma mark - Bookings Delegate Methods

- (void)didReceiveBookingsWithSuccess:(id)object forTicket:(Ticket *)ticket {
    [Utils hideLoadingOn:self];
    if (!_isOnScreen)
        return;
    _groupedBookings = [[BookingsManager instance] groupBookingsByTypeOfClass:object];
    _sortedTypesOfClasses = [[BookingsManager instance] sortTypesOfClasses:_groupedBookings];
    [self setUpTheUI];
    
}

- (void)didReceiveBookingsWithFailure:(id)object forTicket:(Ticket *)ticket {
    [Utils hideLoadingOn:self];
    if (!_isOnScreen)
        return;
    WSError *error = (WSError *)object;
    if (error.errorCode == StatusCodeConnectionError) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:error.errorMessage delegate:self cancelButtonTitle:NSLocalizedString(@"ALERT_CANCEL", nil) otherButtonTitles:NSLocalizedString(@"ALERT_RETRY", nil), nil];
        [alertView show];
    } else {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:error.errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"ALERT_OK", nil) otherButtonTitles: nil];
        [alertView show];
    }
}

#pragma mark - UIAlertViewDelegate Methods

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex != alertView.cancelButtonIndex) {
        [self getBookings];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewDidUnload {
    [self setCategorySegmentedControl:nil];
    [self setBookingsTableView:nil];
    [self setCategoryToolbar:nil];
    [super viewDidUnload];
}
@end
